package pushserver

import (
	"fmt"
	"pushserver/connpool"
	"pushserver/msgqueue"
	"pushserver/persistence"
	"pushserver/util"
	"time"
)

type Sender struct {
	pool  connpool.Pool
	queue msgqueue.Queue
	// TCP代理类
	TcpProxy *TcpProxy
	// 消息持久化容器
	Container persistence.OffMsgContainer
	// 消息发送失败时回调
	FailedCallback func(error)
	// 发送重试次数
	ResendTimes int
	// 重试间隔（毫秒）
	ResendInterval int
}

// 发送消息
func (this *Sender) SendMessage(msg interface{}, user string) error {
	m := msgqueue.Message{
		MsgId:   fmt.Sprintf("1%s", util.Guid()),
		MsgType: msgqueue.Message_ToOne,
		Content: msg,
		To:      user,
	}
	return this.queue.Push(&m)
}

// 发全员广播
func (this *Sender) SendNotice(msg interface{}) {
	this.pool.Foreach(func(userId string) {
		m := msgqueue.Message{
			MsgId:   fmt.Sprintf("2%s", util.Guid()),
			MsgType: msgqueue.Message_ToAll,
			Content: msg,
			To:      userId,
		}
		this.queue.Push(&m)
	})
}

// 客户端新上线处理
func (this *Sender) UpOnline(userid string) {
	fmt.Printf("%s up line \n", userid)
	if this.Container == nil {
		return
	}
	msgs, err := this.Container.GetUserMsg(userid)
	if err != nil {
		return
	}
	for _, v := range msgs {
		msg := v
		this.queue.Push(msg.Message)
	}
}

// conn write
func (this *Sender) send(msg *msgqueue.Message) error {
	msg.TrySendTimes++
	msg.SendTime = time.Now()
	c, err := this.pool.Get(msg.To)
	if err == nil {
		_, err = this.TcpProxy.Write(c, msg.Content)
	}
	return err
}

// 消息发送失败处理
func (this *Sender) msgSendFailed(msg *msgqueue.Message) {
	// 广播信息不处理
	if msg.MsgType == msgqueue.Message_ToAll {
		return
	}
	// 在重试次数范围内，消息重新入队
	if this.ResendTimes >= msg.TrySendTimes {
		this.queue.Push(msg)
		return
	}
	if this.Container == nil {
		return
	}
	m := &persistence.OfflineMsg{
		Message: *msg,
	}
	this.Container.Put(m)
}
